﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// AssetBundle缓存
public class AssetBundleCache
{
	const string ATLAS_PATH = "_atlas_tp_";
	string m_name;          // AssetBundle name

	int m_referencedCount;  // 引用计数
	float m_unloadTime;		// 释放时间

	bool m_isAtlas;         // 是图集
	string m_atlasName; 	// 图集名
	object m_atlasData; 	// 图集数据

	int m_assetCount = 0;	// 资源数
	Dictionary<string, Object> m_dicAssetCache = new Dictionary<string, Object>();

	public AssetBundleCache(string name, AssetBundle ab, bool persistent, int refCount = 1)
	{
		m_name = name;
		Bundle = ab;
		Persistent = persistent;
		ReferencedCount = refCount;

		int index = name.LastIndexOf (ATLAS_PATH);
		if (index != -1) {
			string atlasName = name.Substring (index + ATLAS_PATH.Length).Replace(string.Format(".{0}", Config.AB_SUFFIX), "");

			if (!string.Equals (atlasName, "padding")) {
				m_isAtlas = true;
				m_atlasName = atlasName;
			}
		}

		if (m_isAtlas) {
			GameObject go = ab.LoadAsset<GameObject> (AtlasName);
			if (go != null) {
				m_atlasData = go;
				//LoadManager.Instance.AddSprites (AtlasName, go);
			} else {
				Sprite[] sprites = ab.LoadAllAssets<Sprite> ();
				m_atlasData = sprites;
				//LoadManager.Instance.AddSprites (AtlasName, sprites);
			}
		}
	}

	// AssetBundle
	public AssetBundle Bundle {
		get;
		private set;
	}

	// 是否常驻
	public bool Persistent {
		get;
		set;
	}

	// 引用计数
	public int ReferencedCount {
		get {
			return m_referencedCount;
		}

		set {
			m_referencedCount = value;
			if (IsCanRemove) {
				if (Config.Instance.AssetCacheTime == 0) {
					Unload ();
				} else {
					m_unloadTime = Time.realtimeSinceStartup;
				}
			} else {
				m_unloadTime = 0;
			}
		}
	}

	// 是否可以删除
	public bool IsCanRemove {
		get {
			if (!(!Persistent && ReferencedCount == 0)) {
				return false;
			}

			//if (m_isAtlas && LoadManager.Instance.GetAtlasRefCount (AtlasName) > 0) {
			//	return false;
			//}

			return true;
		}
	}

	// 缓存时间到
	public bool IsTimeOut {
		get {
			return Time.realtimeSinceStartup - m_unloadTime >= Config.Instance.AssetCacheTime;
		}
	}

	public string AtlasName {
		get {
			return m_atlasName;
		}
	}

	public int AssetCount {
		get {
			if (m_assetCount == 0 && Bundle != null) {
				m_assetCount = Bundle.GetAllAssetNames ().Length;
			}
			return m_assetCount;
		}
	}

	//加载资源
	public Object LoadAsset(string name, System.Type type)
	{
		Object asset = null;
		if (!m_dicAssetCache.TryGetValue (name, out asset)) {
			if (Bundle == null) {
				Debuger.LogWarning ("AssetBundle:{0} is null, load asset:{1},type:{2}, fail!!", m_name, name, type.ToString ());
				return null;
			}

			asset = Bundle.LoadAsset (name, type);
			m_dicAssetCache.Add (name, asset);
		}

		m_unloadTime = Time.realtimeSinceStartup;
		return asset;
	}

	//加载资源
	public T LoadAsset<T>(string name) where T:Object
	{
		Object objasset = null;
		T asset = null;
		if (!m_dicAssetCache.TryGetValue (name, out objasset)) {
			asset = Bundle.LoadAsset<T> (name);
			m_dicAssetCache.Add (name, asset);
		} else {
			asset = (T)objasset;
		}

		m_unloadTime = Time.realtimeSinceStartup;
		return asset;
	}

	// 卸载 isUnloadUnusedAsset：此标记谨慎使用，unload的代价比较高，容易导致卡顿
	public void Unload(bool isUnloadUnusedAsset = false)
	{
		if (Bundle != null) {

			Bundle.Unload (m_isAtlas);
			Bundle = null;
			m_assetCount = 0;
			if (isUnloadUnusedAsset) {
				Resources.UnloadUnusedAssets ();
			}
		}

		if (m_isAtlas) {
			if (m_atlasData != null) {
				//if (m_atlasData is GameObject) {
				//	LoadManager.Instance.RemoveSprites (AtlasName, m_atlasData as GameObject);
				//} else if (m_atlasData is Sprite[]) {
				//	LoadManager.Instance.RemoveSprites (AtlasName, m_atlasData as Sprite[]);
				//}
			}
		}

		m_dicAssetCache.Clear ();
		Debuger.Log ("=============Unload ab....:{0}", m_name);
	}

	//卸载自己，不卸载依赖
	public void UnloadSelf()
	{
		if (Bundle == null || m_dicAssetCache.Count == 0) {
			return;
		}

		//资源大于1，并且没有全部载入内存，则不能卸载
		if (Bundle.GetAllAssetNames ().Length > 1 && AssetCount > m_dicAssetCache.Count) {
			return;
		}

		Bundle.Unload (false);
		Bundle = null;

		m_assetCount = 0;
		Debuger.Log ("=============UnloadSelf ab....:{0}", m_name);
	}
}